package org.yaac.client.widget;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent;
import com.google.gwt.view.client.ListDataProvider;

/**
 * handle sorts, the only difference between this handler and default 
 * ColumnSortEvent$ListHandler is that this handler's data provider can be changed
 * so that to make it easier on initilization 
 * 
 * @author Max Zhu (thebbsky@gmail.com)
 *
 * @param <T>
 */
public class SortHandler<T> implements ColumnSortEvent.Handler {

	private final Map<Column<?, ?>, Comparator<T>> comparators = 
		new HashMap<Column<?, ?>, Comparator<T>>();
	
	private ListDataProvider<T> dataProvider;

	/**
	 * column to be sorted
	 */
	private Column<?, ?> column; 
	
	private boolean isSortAscending;
	
	public ListDataProvider<T> getDataProvider() {
		return dataProvider;
	}

	public void setDataProvider(ListDataProvider<T> dataProvider) {
		this.dataProvider = dataProvider;
	}

	@Override
	public void onColumnSort(ColumnSortEvent event) {
		column = event.getColumn();
		isSortAscending = event.isSortAscending();
		
		refresh();
	}

	/**
	 * resort again, potentially this is because data changed in data provider
	 */
	public void refresh() {
		// check if data provider is null
		if (dataProvider == null || dataProvider.getList() == null) {
			return;
		}
		
		// Get the sorted column.
		if (column == null) {
			return;
		}
		
		// Get the comparator.
		final Comparator<T> comparator = comparators.get(column);
		if (comparator == null) {
			return;
		}

		// Sort using the comparator.
		if (isSortAscending) {
			Collections.sort(dataProvider.getList(), comparator);
		} else {
			Collections.sort(dataProvider.getList(), new Comparator<T>() {
				public int compare(T o1, T o2) {
					return - comparator.compare(o1, o2);
				}
			});
		}
	}
	
    public void setComparator(Column<T, ?> column, Comparator<T> comparator) {
    	comparators.put(column, comparator);
    }
}